/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/math/types/Neon
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AENeonMathTypes.h
// Author:		Gianluca Belardelli
// Date:		06/02/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AENEONMATHTYPES_H_
#define _AENEONMATHTYPES_H_

#include <arm_neon.h>

#define AE_VECTORTRANSPOSE4F(A,B,C,D) { \
	float32x2x2_t ABxy = vzip_f32( vget_low_f32(A.m_qfVector), vget_low_f32(B.m_qfVector) );  /* (A.x, B.x) (A.y, B.y) */ \
	float32x2x2_t ABzw = vzip_f32( vget_high_f32(A.m_qfVector), vget_high_f32(B.m_qfVector) ); /* (A.z, B.z) (A.w, B.w) */ \
	float32x2x2_t CDxy = vzip_f32( vget_low_f32(C.m_qfVector), vget_low_f32(D.m_qfVector) );  /* (C.x, D.x) (C.y, D.y) */ \
	float32x2x2_t CDzw = vzip_f32( vget_high_f32(C.m_qfVector), vget_high_f32(D.m_qfVector) ); /* (A.z, B.z) (C.w, D.w) */ \
	A.m_qfVector = vcombine_f32(ABxy.val[0], CDxy.val[0]); \
	B.m_qfVector = vcombine_f32(ABxy.val[1], CDxy.val[1]); \
	C.m_qfVector = vcombine_f32(ABzw.val[0], CDzw.val[0]); \
	D.m_qfVector = vcombine_f32(ABzw.val[1], CDzw.val[1]); \
}

// transpose 3 hkVector4: w component is undefined
#define AE_VECTORTRANSPOSE3F(A,B,C) { \
	float32x2x2_t ABxy = vzip_f32( vget_low_f32( A.m_qfVector ), vget_low_f32( B.m_qfVector ) );  /* (A.x, B.x) (A.y, B.y) */ \
	float32x2x2_t ABzw = vzip_f32( vget_high_f32( A.m_qfVector ), vget_high_f32( B.m_qfVector ) ); /* (A.z, B.z) (A.w, B.w) */ \
	float32x2_t Cx = vget_low_f32( C.m_qfVector );\
	float32x2_t Cz = vget_high_f32( C.m_qfVector );\
	float32x2_t Cy = vset_lane_f32( vgetq_lane_f32( C.m_qfVector, 1), Cz, 0);\
	A.m_qfVector = vcombine_f32(ABxy.val[0], Cx ); \
	B.m_qfVector = vcombine_f32(ABxy.val[1], Cy ); \
	C.m_qfVector = vcombine_f32(ABzw.val[0], Cz ); \
}

typedef float32x4_t AEQuadFloat32;
typedef float32x2_t AESingleFloat32;


// storage type for AEVector4Comparison
typedef uint32x4_t AEVector4fMask;

class AEVector4f;
typedef const AEVector4f &AEVector4fRefParam;

class AESimdFloat32;
typedef const AESimdFloat32 &AESimdFloat32ConstRef;

class AEVector4fComparison;
typedef const AEVector4fComparison &AEVector4fConstRefCompParam;

#if defined(AE_PLATFORM_ANDROID)
#define AE_QUADFLOAT_CONSTANT(a, b, c, d)	{a, b, c, d}
#define AE_QUADINT_CONSTANT(a, b, c, d)		{a, b, c, d}
#endif

#define AE_NEON_CONSTANT2(a, b) {a,b}
#define AE_NEON_CONSTANT4(a, b, c, d) {a,b,c,d}

#define AE_NEON_CONSTANT2F(a, b) AE_NEON_CONSTANT2(a,b)
#define AE_NEON_CONSTANT4F(a, b, c, d) AE_NEON_CONSTANT4(a,b,c,d)
#define AE_NEON_CONSTANT2I(a, b) AE_NEON_CONSTANT2(a,b)
#define AE_NEON_CONSTANT4I(a, b, c, d) AE_NEON_CONSTANT4(a,b,c,d)

#if defined(AE_PLATFORM_IOS) && defined(__llvm__)
// LLVM, no implict uint32 -> float
#define AE_MASK_TO_VECTORf(m) (AEQuadFloat32)vreinterpretq_f32_u32(m)
#endif

#endif // _AENEONMATHTYPES_H_

